#include "ad9833.h"
#include "main.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"

AD9833Struct AD9833;
void AD9833_Init()
{
	GPIO_InitTypeDef GPIO_InitStruct;

	RCC_AHB1PeriphClockCmd(AD9833_FSYNC_GPIOClock, ENABLE);
	RCC_AHB1PeriphClockCmd(AD9833_SDATA_GPIOClock, ENABLE);
	RCC_AHB1PeriphClockCmd(AD9833_SCLK_GPIOClock, ENABLE);
	RCC_AHB1PeriphClockCmd(AD9833_CS_GPIOClock, ENABLE);

	GPIO_InitStruct.GPIO_Pin = AD9833_FSYNC_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(AD9833_FSYNC_Port, &GPIO_InitStruct);

	GPIO_InitStruct.GPIO_Pin = AD9833_SDATA_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(AD9833_SDATA_Port, &GPIO_InitStruct);

	GPIO_InitStruct.GPIO_Pin = AD9833_SCLK_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(AD9833_SCLKC_Port, &GPIO_InitStruct);

	GPIO_InitStruct.GPIO_Pin = AD9833_CS_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(AD9833_CS_Port, &GPIO_InitStruct);

	AD9833_CS_ON;
	delay_ms(100);
	AD9833_Write(0x0100); // Reset
}

static void AD9833_Delay(void)
{
	uint16_t i;
	for (i = 0; i < 65; i++)
		;
}

void AD9833_Write(uint16_t data)
{
	int i;
	AD9833_SCLK_ON;
	AD9833_FSYNC_ON;
	AD9833_FSYNC_OFF;

	for (i = 0; i < 16; i++)
	{
		if (data & 0x8000)
			AD9833_SDATA_ON;
		else
			AD9833_SDATA_OFF;
		AD9833_SCLK_OFF;
		AD9833_SCLK_ON;
		data = data << 1;
	}
	AD9833_FSYNC_ON;
	AD9833_SCLK_OFF;
}

void AD9833_Frequnce_SIN(float data)
{
	uint16_t data_h, data_l;
	uint32_t data_new;

	data_new = 10.73741824 * data;

	data_h = ((data_new >> 14) & 0x3fff) | 0x4000;
	data_l = (data_new & 0x3fff) | 0x4000;

	AD9833_Write(0x0100);
	
	AD9833_Write(0x2100);
	AD9833_Write(data_l);
	AD9833_Write(data_h);
	AD9833_Write(0x2000);
}

void AD9833_Frequnce_TRI(float data)
{
	uint16_t data_h, data_l;
	uint32_t data_new;

	data_new = 10.73741824 * data;

	data_h = ((data_new >> 14) & 0x3fff) | 0x4000;
	data_l = (data_new & 0x3fff) | 0x4000;

	AD9833_Write(0x0100);
	AD9833_Write(0x2100);
	AD9833_Write(data_l);
	AD9833_Write(data_h);
	AD9833_Write(0x2002);
}

void AD9833_Frequnce_SQU(float data)
{
	uint16_t data_h, data_l;
	uint32_t data_new;

	data_new = 10.73741824 * data;

	data_h = ((data_new >> 14) & 0x3fff) | 0x4000;
	data_l = (data_new & 0x3fff) | 0x4000;

	AD9833_Write(0x0100);
	AD9833_Write(0x2100);
	AD9833_Write(data_l);
	AD9833_Write(data_h);
	AD9833_Write(0x2028);
}

void AD9833_Amplitude_Write(unsigned char x)
{
	unsigned char xnum;
	unsigned int xtemp;
	xtemp = 0x1100 | x;
	AD9833_CS_OFF;
	AD9833_Delay();
	for (xnum = 0; xnum < 16; xnum++) // rising
	{
		if (xtemp & 0x8000)
		{
			AD9833_SDATA_ON;
		}
		else
		{
			AD9833_SDATA_OFF;
		}
		xtemp <<= 1;
		AD9833_Delay();
		AD9833_SCLK_ON;
		AD9833_Delay();
		AD9833_SCLK_OFF;
	}
	AD9833_CS_ON;
}

void AD9833_Amplitude_Set(float A)
{
	unsigned char Rtemp = 0;
	float res;
	res = 1000.0 * (A / 5.0);
	Rtemp = res / 39.0625;
	AD9833_Amplitude_Write(Rtemp);
}

extern char freq_change_flag;
void AD9833_stask(void *pvParameters)
{
	while (1)
	{
		if (Display.out_0 == ON)
		{
			if (freq_change_flag == 1)
			{
				switch (AD9833.wave_mode)
				{
				case Sine:
					AD9833_Frequnce_SIN(AD9833.freq);
					break;
				case Square:
					AD9833_Frequnce_SQU(AD9833.freq);
					break;
				case Triangle:
					AD9833_Frequnce_TRI(AD9833.freq);
					break;
				default:
					break;
				}
				freq_change_flag = 0;
			}
			AD9833_Amplitude_Set(AD9833.Amplitude);
		}
		vTaskDelay(30);
	}
}
